[Note] Node.js + express: Server & Routing


Posted by urlun0404 on 2022-12-06

之前有一篇用Node.js原生語法建立伺服器的文章提過說,一般都會使用express這個模組去建立伺服器,因為用express建立伺服器更簡單、更便利😂

這篇就是記錄如何用express設定伺服器、靜態文件和路由(routing)。


Server

從以下範例可以看出用express設定伺服器確實比使用Node.js原生語法設定伺服器來的簡單許多,但是express的伺服器回應(response)每次都只能 sendsendFile 一次

const path = require('path');
const express = require('express');
const app = express();

/* Request handling */
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, index.html));
    // res.send(<h3>Welcome</h3>);   // 錯誤
});

app.get('/about', (req, res) => {
    res.send('About page');
});


// ... other routing


// 讓伺服器監聽port 3000的請求
app.listen(3000, () => {
    console.log('Server is running on the port 3000');
});



Static files

靜態文件(static files)是任何非伺服器端產生、需要提供給網站的資源,譬如像是CSS、圖片檔等,都可稱作是靜態文件。

在express中,靜態文件的處理是要透過middleware機制去設定放置靜態文件的資料夾,假設放置靜態文件的資料夾名為"public",我們要在路由(routing)之前設定middleware:

// middleware
app.use(express.static('public'));

app.use() 表示要使用middle ware;而 express.static() 括號內則表示要放置靜態文件的資料夾。



Routing & Status Code

當使用者透過連結或者自行輸入網址會導向至相對應的頁面,而路由就是用來達成這樣的事情,這一小節分為三種類型的路由:

  • Routing for patterns
  • Routing for query
  • Routing for all

Routing for patterns

第一個要來處理動態路由,可以透過 req.params 取得參數物件,而範例以解構(destructuring)的方式去取得參數product:

// Routing for patterns
app.get('/products/:product', (req, res) => {
    const { product } = req.params;
    res.send(`The entered product is ${product}.`);
});


Routing for query

第二種路由類型則是要處理表單送出的路由,假設已經在首頁設定好一個表單,表單的action可以設定送出請求後的路由:

<form action="/formHandling" method="GET">
    ...
</form>


以下範例考慮表單的method可設定為GET或POST兩種請求:

method = "GET"

GET請求比較容易,只需要將路由設定成 app.get('/* 表單送出路由 */', ...);

app.get('/formHandling', (req, res) => {
    const { fullname, age } = req.query;   // 取得表單欄位值
    res.send(`Hi, ${fullname}. Your age is ${age}.`)
});


method = "POST"

在express裡面,表單的POST請求則是要多設定一個middleware:

const bodyParser = require('body-parser');

// middleware
app.use(bodyParser.urlencoded({ extended: true }));

// Handle POST request
app.post('/formHandling', (req, res) => {
    const { fullname, age } = req.body;
    res.send(`Hi, ${fullname}. Thanks for posting.`);
});


Routing for all

最後一個要處理的是任一路由,也就是假設使用者輸入沒有特別設定(或者亂打一通)的網址列,可以使用 * 顯示常見的 "404" 畫面:

// Routing for all
app.get('*', (req, res) => {
    res.status(404)   // 設定 404 狀態碼
       .send(<h1> 404 NOT FOUND </h1>);
});

設定這種路由要注意的是,只能放在其他路由的最下面,否則不管輸入什麼網址都會直接轉向至這個路由。



HTTP Requests

常用的HTTP Requests有以下幾種:

  • GET: Read
  • POST: Create
  • PUT: Replace/ Update ALL
  • PATCH: Replace/ Update Partial Data
  • DELETE

在此之前都只用到 GETPOST requests,後端的server可以處理以上提到的五種需求,但是如果前端HTML頁面建立了一個表格提供修改資料,不過HTML Form的method卻只有GET和POST,這種時候可以借助第三方套件來處理其他類型的requests。

這篇文章以method-override示範,根據文件express要新增以下資訊:

const methodOcerride = require("method-override");

// override with POST having ?_method=PUT
app.use(methodOverride("_method"));

然後HTML的form method可以設定成POST,但是action後面要新增參數:

<form action="/update/:id?_method=PUT" method="POST">
...
</form>



References
Using middleware @express
Serving static files in Express @express
2022網頁開發全攻略(HTML, CSS, JavaScript, React, SQL, Node, more)


#Backend #node.js #Express







Related Posts

CS 50 Dynamic Memory Allocation

CS 50 Dynamic Memory Allocation

何謂演算法技術面試?讀《Cracking the Coding Interview(提升程式設計師的面試力)》

何謂演算法技術面試?讀《Cracking the Coding Interview(提升程式設計師的面試力)》

【THM Walkthrough】Lateral Movement and Pivoting (1)

【THM Walkthrough】Lateral Movement and Pivoting (1)


Comments